package c.a.md.androidvideo;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class VideoAudioRecordActivity extends AppCompatActivity implements SurfaceHolder.Callback
{

    int width = 1280;
    int height = 720;
    int frameRate = 30;
    private SurfaceHolder mSurfaceHolder;
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    private H264Encoder encoder;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_audio_record);
        mSurfaceView = findViewById(R.id.surface);
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        if (supportH264Codec())
        {
            Log.e("s", "support H264 hard codec");
        } else
        {
            Log.e("s", "Not support H264 hard codec");
        }
        encoder = new H264Encoder(width, height, frameRate);
    }

    private boolean supportH264Codec()
    {
        // 遍历支持的编码格式信息
        if (Build.VERSION.SDK_INT >= 18)
        {
            for (int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--)
            {
                MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j);

                String[] types = codecInfo.getSupportedTypes();
                for (int i = 0; i < types.length; i++)
                {
                    if (types[i].equalsIgnoreCase("video/avc"))
                    {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void click(View view)
    {
        checkFirst();
    }

    private void checkFirst()
    {
        List<String> pers = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED)
        {
            pers.add(Manifest.permission.CAMERA);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED)
        {
            pers.add(Manifest.permission.RECORD_AUDIO);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED)
        {
            pers.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            pers.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }

        if (pers.size() > 0)
        {
            ActivityCompat.requestPermissions(this, (String[]) pers.toArray(), 12);
        } else
        {
            process();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
    {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 12)
        {
            process();
        }
    }

    private void process()
    {
        initCamera();
        encoder.startEncoder();
    }

    private void initCamera()
    {
        if (mSurfaceHolder == null)
            return;

        mCamera = Camera.open();
        mCamera.setDisplayOrientation(90);
        Camera.Parameters p = mCamera.getParameters();
        p.setPreviewFormat(ImageFormat.NV21);
        p.setPreviewSize(width, height);
        try
        {
            mCamera.setParameters(p);
            mCamera.setPreviewDisplay(mSurfaceHolder);
            mCamera.setPreviewCallback(new Camera.PreviewCallback()
            {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera)
                {
                    encoder.putData(data);
                }
            });
            mCamera.startPreview();
        } catch (Exception e)
        {
            Toast.makeText(this, "异常", Toast.LENGTH_SHORT).show();
        }
    }

    private void destroyCamera()
    {
        if (mCamera != null)
        {
            try
            {
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
                if (encoder != null)
                {
                    encoder.stopEncoder();
                }
            } catch (Exception e)
            {
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        mSurfaceHolder = holder;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        destroyCamera();
    }
}
